package pers.dawnyang.config.shiro;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.LogoutAware;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import pers.dawnyang.common.enums.ResultEnum;
import pers.dawnyang.config.SpringUtil;
import pers.dawnyang.config.exception.BusinessException;
import pers.dawnyang.modular.system.domain.common.RoleInfo;
import pers.dawnyang.modular.system.domain.common.UserInfo;
import pers.dawnyang.modular.system.service.SystemService;

/**
 * 
 * @author dawn yang
 * 
 */

public class ShiroUtil {

  private static MemorySessionDAO sessionDAO = SpringUtil.getBean(MemorySessionDAO.class);

  private static SystemService systemService = SpringUtil.getBean(SystemService.class);

  /**
   * 获取指定用户名的Session
   * 
   * @param username
   * @return
   */
  private static Session getSessionByUsername(String userCode) {
    Collection<Session> sessions = sessionDAO.getActiveSessions();
    Object attribute;
    for (Session session : sessions) {
      attribute = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
      if (attribute == null) {
        continue;
      }
      String userCodeSession =
          (String) ((SimplePrincipalCollection) attribute).getPrimaryPrincipal();
      if (StringUtils.isBlank(userCodeSession)) {
        continue;
      }
      if (Objects.equals(userCodeSession, userCode)) {
        return session;
      }
    }
    return null;
  }

  /**
   * 删除用户缓存信息
   * 
   * @param userCode 用户名
   * @param isRemoveSession 是否删除session，删除后用户需重新登录
   */
  public static void kickOutUser(String userCode, boolean isRemoveSession) {
    Session session = getSessionByUsername(userCode);
    if (session == null) {
      return;
    }

    Object attribute = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
    if (attribute == null) {
      return;
    }

    String userCodeSession = (String) ((SimplePrincipalCollection) attribute).getPrimaryPrincipal();
    if (!userCode.equals(userCodeSession)) {
      return;
    }

    // 删除session
    if (isRemoveSession) {
      sessionDAO.delete(session);
    }
    DefaultWebSecurityManager securityManager =
        (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
    Authenticator authc = securityManager.getAuthenticator();
    // 删除cache，在访问受限接口时会重新授权
    ((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
  }

  // 获得当前用户最大的角色等级
  public static Long getUserMinRoleLevel() {
    Subject subject = SecurityUtils.getSubject();
    String userCode = (String) subject.getPrincipal();
    UserInfo user = systemService.getUserInfo(userCode);
    if (null == user) {
      throw new BusinessException(ResultEnum.ERROR_SESSION_EXPIRES);
    }
    List<RoleInfo> roleList = user.getRoleList();
    // 数值越小，等级越高
    Long minRoleSort =
        roleList.stream().min(Comparator.comparing(RoleInfo::getRoleSort)).get().getRoleSort();
    return minRoleSort;
  }

  public static Long getUserId() {
    Subject subject = SecurityUtils.getSubject();
    String userCode = (String) subject.getPrincipal();
    UserInfo user = systemService.getUserInfo(userCode);
    return user.getUserId();
  }

}
